#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cpuinfo.h"

void main_func1();

int main(int argc, char** argv)
{
	main_func1();
	
	return 0;
}

void main_func1()
{
	int arg = 0x01;
	
	int eax = arg;
	int ebx = 0;
	int ecx = 0;
	int edx = 0;
	eax = cpu_id(eax, &ebx, &ecx, &edx);
	printf("0x%x 0x%x 0x%x 0x%x\n", eax, ebx, ecx, edx);
	
	if ( arg == 0x01 )
	{
		int st = eax & 0x0000000f;
		int md = (eax & 0x000000f0) >> 4;
		int fm = (eax & 0x00000f00) >> 8;
		int tp = (eax & 0x00003000) >> 12;
		int em = (eax & 0x000f0000) >> 16;
		int ef = (eax & 0x0ff00000) >> 20;
		
		//printf("Vendor\t\t : %s\n", v);
		printf("Stepping\t : %X\n", st);
		printf("Model\t\t : %X\n", md);
		printf("Family\t\t : %X\n", fm);
		printf("Type\t\t : %X\n", tp);
		printf("Ext model\t : %X\n", em);
		printf("Ext family\t : %X\n", ef);
		
		int fpu   = (edx & 0x00000001) >> 0; //Onboard x87 FPU
		int vme   = (edx & 0x00000002) >> 1; //Virtual 8086 mode extensions (such as VIF, VIP, PIV)
		int de    = (edx & 0x00000004) >> 2; //Debugging extensions (CR4 bit 3)
		int pse   = (edx & 0x00000008) >> 3; //Page Size Extension
		int tsc   = (edx & 0x00000010) >> 4; //Time Stamp Counter
		int msr   = (edx & 0x00000020) >> 5; //Model-specific registers
		int pae   = (edx & 0x00000040) >> 6; //Physical Address Extension
		int mce   = (edx & 0x00000080) >> 7; //Machine Check Exception
		int cx8   = (edx & 0x00000100) >> 8; //CMPXCHG8 (compare-and-swap) instruction
		int apic  = (edx & 0x00000200) >> 9; //Onboard Advanced Programmable Interrupt Controller
		//int     = (edx & 0x00000400) >> 10; //reserved
		int sep   = (edx & 0x00000800) >> 11; //SYSENTER and SYSEXIT instructions
		int mtrr  = (edx & 0x00001000) >> 12; //Memory Type Range Registers
		int pge   = (edx & 0x00002000) >> 13; //Page Global Enable bit in CR4
		int mca   = (edx & 0x00004000) >> 14; //Machine check architecture
		int cmov  = (edx & 0x00008000) >> 15; //Conditional move and FCMOV instructions
		int pat   = (edx & 0x00010000) >> 16; //Page Attribute Table
		int	pse36 = (edx & 0x00020000) >> 17; //36-bit page size extension
		int clfsh = (edx & 0x00040000) >> 18; //Processor Serial Number
		int psn   = (edx & 0x00080000) >> 19; //CLFLUSH instruction (SSE2)
		//int     = (edx & 0x00100000) >> 20; //reserved
		int ds    = (edx & 0x00200000) >> 21; //Debug store: save trace of executed jumps
		int acpi  = (edx & 0x00400000) >> 22; //Onboard thermal control MSRs for ACPI
		int mmx   = (edx & 0x00800000) >> 23; //MMX instructions
		int fxsr  = (edx & 0x01000000) >> 24; //FXSAVE, FXRESTOR instructions, CR4 bit 9 
		int sse   = (edx & 0x02000000) >> 25; //SSE instructions (a.k.a. Katmai New Instructions)
		int sse2  = (edx & 0x04000000) >> 26; //SSE2 instructions
		int ss    = (edx & 0x08000000) >> 27; //CPU cache supports self-snoop
		int htt   = (edx & 0x10000000) >> 28; //Hyper-threading 
		int tm    = (edx & 0x20000000) >> 29; //Thermal monitor automatically limits temperature
		int ia64  = (edx & 0x40000000) >> 30; //IA64 processor emulating x86
		int pbe   = (edx & 0x80000000) >> 31; //Pending Break Enable (PBE# pin) wakeup support
	
		printf("fpu\t\t : %d\n", fpu);
		printf("vme\t\t : %d\n", vme);
		printf("de\t\t : %d\n", de);
		printf("pse\t\t : %d\n", pse);
		printf("tsc\t\t : %d\n", tsc);
		printf("msr\t\t : %d\n", msr);
		printf("pae\t\t : %d\n", pae);
		printf("mce\t\t : %d\n", mce);
		printf("cx8\t\t : %d\n", cx8);
		printf("apic\t\t : %d\n", apic);
		printf("sep\t\t : %d\n", sep);
		printf("mtrr\t\t : %d\n", mtrr);
		printf("pge\t\t : %d\n", pge);
		printf("mca\t\t : %d\n", mca);
		printf("cmov\t\t : %d\n", cmov);
		printf("pat\t\t : %d\n", pat);
		printf("pse36\t\t : %d\n", pse36);
		printf("psn\t\t : %d\n", psn);
		printf("clfsh\t\t : %d\n", clfsh);
		printf("ds\t\t : %d\n", ds);
		printf("acpi\t\t : %d\n", acpi);
		printf("mmx\t\t : %d\n", mmx);
		printf("fxsr\t\t : %d\n", fxsr);
		printf("sse\t\t : %d\n", sse);
		printf("sse2\t\t : %d\n", sse2);
		printf("ss\t\t : %d\n", ss);
		printf("htt\t\t : %d\n", htt);
		printf("tm\t\t : %d\n", tm);
		printf("ia64\t\t : %d\n", ia64);
		printf("pbe\t\t : %d\n", pbe);
		
		puts("ecx----");
		int sse3      = (ecx & 0x00000001) >> 0; //Prescott New Instructions-SSE3 (PNI)
		int pclmulqdq = (ecx & 0x00000002) >> 1; //PCLMULQDQ support
		int dtes64    = (ecx & 0x00000004) >> 2; //64-bit debug store (edx bit 21)
		int monitor   = (ecx & 0x00000008) >> 3; //MONITOR and MWAIT instructions (SSE3)
		int dscpl     = (ecx & 0x00000010) >> 4; //CPL qualified debug store
		int vmx       = (ecx & 0x00000020) >> 5; //Virtual Machine eXtensions 
		int smx       = (ecx & 0x00000040) >> 6; //Safer Mode Extensions (LaGrande)
		int est       = (ecx & 0x00000080) >> 7; //Enhanced SpeedStep
		int tm2       = (ecx & 0x00000100) >> 8; //Thermal Monitor 2
		int ssse3     = (ecx & 0x00000200) >> 9; //Supplemental SSE3 instructions
		int cnxtid    = (ecx & 0x00000400) >> 10;//L1 Context ID
		//int        = (ecx & 0x00000800) >> 11;//reserved
		int fma       = (ecx & 0x00001000) >> 12;//Fused multiply-add (FMA3)
		int cx16      = (ecx & 0x00002000) >> 13;//CMPXCHG16B instruction
		int xtpr      = (ecx & 0x00004000) >> 14;//Can disable sending task priority messages
		int pdcm      = (ecx & 0x00008000) >> 15;//Perfmon & debug capability
		//int         = (ecx & 0x00010000) >> 16;//reserved
		int pcid	  = (ecx & 0x00020000) >> 17;//Process context identifiers (CR4 bit 17)
		int dca	      = (ecx & 0x00040000) >> 18;//Direct cache access for DMA writes[8][9]
		int sse41     = (ecx & 0x00080000) >> 19;//SSE4.1 instructions
		int sse42     = (ecx & 0x00100000) >> 20;//SSE4.2 instructions
		int x2apic    = (ecx & 0x00200000) >> 21;//x2APIC support
		int movbe     = (ecx & 0x00300000) >> 22;//MOVBE instruction (big-endian)
		int popcnt    = (ecx & 0x00800000) >> 23;//POPCNT instruction
		int tscdeadlne= (ecx & 0x01000000) >> 24;//APIC supports one-shot operation using a TSC deadline value
		int aes       = (ecx & 0x02000000) >> 25;//AES instruction set
		int xsave     = (ecx & 0x04000000) >> 26;//XSAVE, XRESTOR, XSETBV, XGETBV
		int osxsave   = (ecx & 0x08000000) >> 27;//XSAVE enabled by OS
		int avx       = (ecx & 0x10000000) >> 28;//Advanced Vector Extensions
		int f16c      = (ecx & 0x20004000) >> 29;//F16C (half-precision) FP support
		int rdrnd     = (ecx & 0x40004000) >> 30;//RDRAND (on-chip random number generator) support
		int hypervisor= (ecx & 0x80004000) >> 31;//Running on a hypervisor (always 0 on a real CPU, but also with some hypervisors)
		
		printf("sse3\t\t : %d\n", sse3);
		printf("pclmulqdq\t : %d\n", pclmulqdq);
		printf("dtes64\t\t : %d\n", dtes64);
		printf("monitor\t\t : %d\n", monitor);
		printf("dscpl\t\t : %d\n", dscpl);
		printf("vmx\t\t : %d\n", vmx);
		printf("smx\t\t : %d\n", smx);
		printf("est\t\t : %d\n", est);
		printf("tm2\t\t : %d\n", tm2);
		printf("ssse3\t\t : %d\n", ssse3);
		printf("cnxtid\t\t : %d\n", cnxtid);
		printf("fma\t\t : %d\n", fma);
		printf("cx16\t\t : %d\n", cx16);
		printf("xtpr\t\t : %d\n", xtpr);
		printf("pdcm\t\t : %d\n", pdcm);
		printf("pcid\t\t : %d\n", pcid);
		printf("dca\t\t : %d\n", dca);
		printf("sse41\t\t : %d\n", sse41);
		printf("sse42\t\t : %d\n", sse42);
		printf("x2apic\t\t : %d\n", x2apic);
		printf("movbe\t\t : %d\n", movbe);
		printf("popcnt\t\t : %d\n", popcnt);
		printf("tscdeadlne\t : %d\n", tscdeadlne);
		printf("aes\t\t : %d\n", aes);
		printf("xsave\t\t : %d\n", xsave);
		printf("osxsave\t\t : %d\n", osxsave);
		printf("avx\t\t : %d\n", avx);
		printf("f16c\t\t : %d\n", f16c);
		printf("rdrnd\t\t : %d\n", rdrnd);
		printf("hypervisor\t : %d\n", hypervisor);
	}
	
	char cpu_brand[49] = {0};
	
	arg = 0x80000002;
	eax = arg;
	ebx = 0;
	ecx = 0;
	edx = 0;
	eax = cpu_id(eax, &ebx, &ecx, &edx);
	
	memcpy((char*)cpu_brand, (char*)&eax, 4);
	memcpy((char*)(cpu_brand+4), (char*)&ebx, 4);
	memcpy((char*)(cpu_brand+8), (char*)&ecx, 4);
	memcpy((char*)(cpu_brand+12), (char*)&edx, 4);
	
	printf("0x%x 0x%x 0x%x 0x%x\n", eax, ebx, ecx, edx);

	arg = 0x80000003;
	eax = arg;
	ebx = 0;
	ecx = 0;
	edx = 0;
	eax = cpu_id(eax, &ebx, &ecx, &edx);
	printf("0x%x 0x%x 0x%x 0x%x\n", eax, ebx, ecx, edx);
	
	memcpy(cpu_brand+16, (char*)&eax, 4);
	memcpy(cpu_brand+20, (char*)&ebx, 4);
	memcpy(cpu_brand+24, (char*)&ecx, 4);
	memcpy(cpu_brand+28, (char*)&edx, 4);

	arg = 0x80000004;
	eax = arg;
	ebx = 0;
	ecx = 0;
	edx = 0;
	eax = cpu_id(eax, &ebx, &ecx, &edx);
	printf("0x%x 0x%x 0x%x 0x%x\n", eax, ebx, ecx, edx);
	
	memcpy(cpu_brand+32, (char*)&eax, 4);
	memcpy(cpu_brand+36, (char*)&ebx, 4);
	memcpy(cpu_brand+40, (char*)&ecx, 4);
	memcpy(cpu_brand+44, (char*)&edx, 4);
	
	puts(cpu_brand);
	
	//char cpu_aaa[5] = {0};
	arg = 0x80000008;
	eax = arg;
	ebx = 0;
	ecx = 0;
	edx = 0;
	eax = cpu_id(eax, &ebx, &ecx, &edx);
	printf("0x%x 0x%x 0x%x 0x%x\n", eax, ebx, ecx, edx);
}

